/**
 * @file main.c
 * @brief COT操作系统示例程序，展示了任务创建、条件变量、任务同步等基本功能
 * @details 该示例程序创建多个任务，演示了：
 *          - 任务的创建和调度
 *          - 条件变量的使用
 *          - 任务间的同步
 *          - 任务的等待和唤醒机制
 */

#include "cot_os.h"
#include <stdio.h>

/**
 * @brief 日志打印宏，输出当前时间、任务ID、函数名和行号等信息
 * @param fmt 格式化字符串
 * @param arg 可变参数列表
 */
#define LOG_PRINTF(fmt, arg...) printf("[%u ms][%u][%s:%d] " fmt "\r\n", \
                                       GetTimerMs(),                     \
                                       cotOs_Pid(),                      \
                                       __FUNCTION__, __LINE__, ##arg)

#ifdef _WIN32
#include <windows.h>
/**
 * @brief Windows平台获取系统时间(毫秒)
 * @return 系统启动以来的毫秒数
 */
size_t GetTimerMs(void)
{
    return GetTickCount();
}
#else
#include <sys/time.h>
/**
 * @brief Linux平台获取系统时间(毫秒)
 * @return 系统当前时间的毫秒数
 */
uint32_t GetTimerMs(void)
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return (uint32_t)(tv.tv_sec) * 1000 + (size_t)(tv.tv_usec) / 1000;
}
#endif

/** @brief 全局条件变量，用于任务间的同步 */
CotOSCondition_t g_cv;
/** @brief 任务1的栈空间 */
uint8_t g_stackBuf[1024 * 10];
/** @brief 任务2的栈空间 */
uint8_t g_stackBuf2[1024 * 10];
/** @brief 任务3的栈空间 */
uint8_t g_stackBuf3[1024 * 10];

/**
 * @brief 任务1 - 条件变量等待示例
 * @param arg 任务参数
 * @details 该任务展示了条件变量的等待操作：
 *          - 无限循环等待条件变量信号
 *          - 每次被唤醒后计数器加1
 */
void taskfunc1(int arg)
{
    int t = 0;  /* 计数器 */
    int t1 = 5; /* 测试变量 */

    LOG_PRINTF("taskfunc-1-0: %p  %p\n", &t, &t1);

    while (1)
    {
        LOG_PRINTF("taskfunc-1-0\n");
        /* 等待条件变量信号 */
        cotOs_ConditionWait(&g_cv);
        t++;
    }
}

/**
 * @brief 任务2 - 条件变量通知示例
 * @param arg 任务参数，用于区分不同的任务实例
 * @details 该任务展示了条件变量的通知操作：
 *          - 循环5次，每次等待1秒后发送条件变量信号
 *          - 演示了任务的定时等待功能
 */
void taskfunc2(int arg)
{
    int t = 5; /* 循环计数器 */

    LOG_PRINTF("taskfunc-2-0: %p\n", &t);

    while (t--)
    {
        LOG_PRINTF("taskfunc-2(%d)-0\n", arg);
        // cotOs_Wait(3000);
        LOG_PRINTF("taskfunc-2(%d)-1\n", arg);
        /* 等待1秒 */
        cotOs_Wait(1000);
        /* 发送条件变量信号 */
        cotOs_ConditionNotify(&g_cv);
    }

    LOG_PRINTF("taskfunc-2-end\n");
}

/**
 * @brief 任务3 - 简单任务示例
 * @param arg 任务参数
 * @details 该任务展示了基本的任务操作：
 *          - 使用静态变量计数
 *          - 演示任务的定时等待功能
 */
void taskfunc3(int arg)
{
    static int t = 0; /* 静态计数器 */

    LOG_PRINTF("taskfunc-3-0: %p\n", &t);

    // while(1)
    {
        t++;

        // LOG_PRINTF("taskfunc-3-0: %d\n", t);
        // cotOs_Wait(1000);
        LOG_PRINTF("taskfunc-3-1\n");
        // cotOs_ConditionWait(&g_cv);
        /* 等待1秒 */
        cotOs_Wait(1000);
        // LOG_PRINTF("taskfunc-3-2\n");
        // cotOs_Wait(1000);
        // LOG_PRINTF("taskfunc-3-3\n");
        // cotOs_Wait(1000);
    }

    LOG_PRINTF("taskfunc-3-1 end\n");
}

/**
 * @brief 任务4 - 循环计算示例
 * @param arg 任务参数
 * @details 该任务展示了一个计算过程：
 *          - 使用静态变量进行累乘计算
 *          - 每次计算后等待1秒
 *          - 直到计算结果大于等于10才结束
 */
void taskfunc4(int arg)
{
    static int t = 1; /* 静态计算变量 */

    LOG_PRINTF("taskfunc-%d-0: %p\n", arg, &arg);

    while (t < 10)
    {
        t *= 2; /* 每次将t乘以2 */
        LOG_PRINTF("taskfunc-%d-0 : %d\n", arg, t);
        /* 等待1秒 */
        cotOs_Wait(1000);
        // cotOs_Top();
    }

    LOG_PRINTF("taskfunc-%d-%d end\n", arg, t);
    // COT_OS_GET_STACK(sp);

    // LOG_PRINTF("taskfunc-%d-0: %lx\n", arg, sp);
}

void taskfunc5(int arg)
{
    LOG_PRINTF("taskfunc-%d-0\n", arg);

    /* 创建两个子任务 */
    cotOsTask_t task1 = cotOs_CreatTask(taskfunc4, "share_task4", 1);
    cotOsTask_t task2 = cotOs_CreatTask(taskfunc3, "share_task3", 2);

    // while(1)
    {
        LOG_PRINTF("taskfunc-%d-0\n", arg);
        cotOs_Wait(1000);
        /* 等待task1完成 */
        cotOs_Join(task1);
        LOG_PRINTF("taskfunc-%d-0: task1 end\n", arg);
        /* 等待task2完成 */
        cotOs_Join(task2);
        LOG_PRINTF("taskfunc-%d-0: task2 end\n", arg);
    }

    LOG_PRINTF("taskfunc-%d-0 end\n", arg);
}

/**
 * @brief 任务6 - 无限等待条件变量示例
 * @param arg 任务参数
 * @details 该任务展示了条件变量的永久等待：
 *          - 无限循环等待条件变量信号
 *          - 演示了任务的阻塞等待机制
 */
void taskfunc6(int arg)
{
    LOG_PRINTF("taskfunc-%d-0: %p\n", arg, &arg);

    while (1)
    {
        LOG_PRINTF("taskfunc-%d-0\n", arg);
        // cotOs_Wait(2000);
        /* 等待条件变量信号 */
        cotOs_ConditionWait(&g_cv);
    }

    LOG_PRINTF("taskfunc-%d-0 end\n", arg);
}

/**
 * @brief 主函数 - 系统初始化和任务创建
 * @return 程序退出码
 * @details 主函数完成以下操作：
 *          1. 初始化COT操作系统
 *          2. 初始化条件变量
 *          3. 创建多个任务
 *          4. 启动系统调度
 */
int main(void)
{
    /* 初始化COT操作系统，设置时间获取函数 */
    cotOs_Init(GetTimerMs);

    /* 初始化条件变量 */
    cotOs_ConditionInit(&g_cv);

    /* 创建两个任务2实例，使用指定的栈空间 */
    cotOs_CreatTaskWithStack(taskfunc2, "task2-1", g_stackBuf, sizeof(g_stackBuf), 1);
    cotOs_CreatTaskWithStack(taskfunc2, "task2-2", g_stackBuf2, sizeof(g_stackBuf2), 2);
    // cotOs_CreatTaskWithStack(taskfunc5, "task5", g_stackBuf3, sizeof(g_stackBuf3), 9);

    // cotOs_CreatTask(taskfunc2, "task2-1", 5);
    // cotOs_CreatTask(taskfunc2, "task2-2", 2);
    /* 创建任务5，使用系统分配的栈空间 */
    cotOs_CreatTask(taskfunc5, "task5", 9);

    printf("Start\n");

    /* 启动系统调度 */
    cotOs_Start();

    printf("END\n");

    return 0;
}
